package org.basis.netty.chat.protocol;

import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import org.basis.netty.chat.message.RpcRequestMessage;
import org.basis.netty.chat.message.RpcResponseMessage;
import org.basis.netty.chat.rpc.server.service.HelloService;
import org.basis.netty.chat.rpc.server.service.ServicesFactory;

import java.lang.reflect.Method;

/**
 * rpc请求处理器
 *
 * @author Mr_wenpan@163.com 2021/09/28 16:11
 */
@Slf4j
@ChannelHandler.Sharable
public class RpcRequestMessageHandler extends SimpleChannelInboundHandler<RpcRequestMessage> {

    /**
     * @param ctx     channel处理器上下文
     * @param message rpc请求消息
     * @author Mr_wenpan@163.com 2021/9/28 5:08 下午
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, RpcRequestMessage message) throws Exception {
        RpcResponseMessage responseMessage = new RpcResponseMessage();
        // 保证响应消息的序列号和请求消息的序列号一致
        responseMessage.setSequenceId(message.getSequenceId());

        try {
            // 通过请求消息中的接口名称获取到该接口的对应实现类
            // 由于我们这里只是做测试，只有一个service所以直接强转
            HelloService service = (HelloService) ServicesFactory.getService(Class.forName(message.getInterfaceName()));
            // 通过请求消息中的调用方法名，在接口中获取到要调用的方法对象
            Method method = service.getClass().getMethod(message.getMethodName());
            // 调用接口实现类的指定方法
            Object invoke = method.invoke(service, message.getParameterValue());

            // 调用成功
            responseMessage.setReturnValue(invoke);

        } catch (Exception ex) {
            // 方法调用失败，返回异常调用
            ex.printStackTrace();
            responseMessage.setExceptionValue(ex);
        }

        // 执行结果写回给客户端
        ctx.writeAndFlush(responseMessage);
    }

}
